#include "Parser.h"

string _sLine;
vector<string> tokens;
ifstream _infile;
int _pos;
int _tokenIndex;
int _tokenAmount;
int _size;
int _procedure;
TNode _nodeList[100000];
vector<Pattern_node> patternTree;

/**
Remove, trim and split is the operation on string
**/
string remove(string aimString, char sep) {
	string output="";
	int l = aimString.length();
	int i;
	for (i=0;i<l;i++) {
		if (aimString[i]==sep) {
			continue;
		} else {
			output+=aimString[i];
		}
	}
	return output;
}

string trim(string aimString) {
	string output = aimString;
	output.erase(0, output.find_first_not_of(" \r\t\n"));      
	output.erase(output.find_last_not_of(" \r\t\n")+1);  
	return output;
}

vector<string> split(string s, char sep) {
	vector<string> strvec;
	string strtemp;
	string::size_type pos1, pos2;
	pos2 = s.find(sep);
	pos1 = 0;        
	while (string::npos != pos2)
	{
		strvec.push_back(s.substr(pos1, pos2 - pos1));
		pos1 = pos2 + 1;
		while ((pos1<s.size())&&(s.at(pos1)==sep)) {
			pos1++;
		}
		pos2 = s.find(sep, pos1);
	}
	strvec.push_back(s.substr(pos1));
	return strvec;
}

bool Parser::isConstant(string str){
	
	stringstream convert(str);
	int result;
	if(convert>>result)
	{
		return true;
	}
    return false;
}

/**
Below is to fetch the private parameters in Parser
**/

AST Parser::getAST(){
	return _ast;
}

VarTable Parser::getVarTable(){
	return _varTable;
}

ProcTable Parser::getProcTable() {
	return _procTable;
}

ConstTable Parser::getConstTable() {
	return _constTable;
}

Parent Parser::getParent() {
	return _parent;
}

Follows Parser::getFollows() {
	return _follows;
}

Modifies Parser::getModifies() {
	return _modifies;
}

Uses Parser::getUses() {
	return _uses;
}

Calls Parser::getCalls() {
	return _calls;
}

LoopTable Parser::getLoops() {
	return _loopTable;
}

PatternTable Parser::getPatternTable() {
	return _patternTable;
}

StmtLstTable Parser::getStmtLstTable() {
	return _stmtLstTable;
}

PlusTable Parser::getPlus() {
	return _plusTable;
}

MinusTable Parser::getMinus() {
	return _minusTable;
}

TimesTable Parser::getTimes() {
	return _timesTable;
}

Contains Parser::getContains() {
	return _contains;
}
/**
Below is all kinds of operations
**/
bool isAssignment() {
	if(tokens.at(_tokenIndex).find("=")!=string::npos){
		return true;
	}
	return false;
}
bool isWhile() {
	int size = tokens[_tokenIndex].size();
	vector<string> vLine = split(trim(remove(tokens[_tokenIndex], '{')), ' ');
	if ((tokens[_tokenIndex].at(size-1)=='{')
			&& (vLine.size()==2) 
			&& (vLine[0].compare("while")==0)) {
		return true;
	}
	return false;
}
bool isIf() {
	int size = tokens[_tokenIndex].size();
	vector<string> vLine = split(trim(remove(tokens[_tokenIndex], '{')), ' ');
	if ((tokens[_tokenIndex].at(size-1)=='{')
			&& (vLine.size()==3)
			&& (vLine[0].compare("if")==0)
			&& (vLine[2].compare("then")==0)) {
		return true;
	}
	return false;
}
bool isElse() {
	int size = tokens[_tokenIndex].size();
	vector<string> vLine = split(trim(remove(tokens[_tokenIndex], '{')), ' ');
	if ((tokens[_tokenIndex].at(size-1)=='{')
			&& (vLine.size()==1)
			&& (vLine[0].compare("else")==0)) {
		return true;
	}
	return false;
}
bool isCall() {	
	vector<string> vLine = split(tokens[_tokenIndex], ' ');
	if ((vLine.size()==2)
			&& (vLine[0].compare("call")==0)) {
		return true;
	}
	return false;
}
bool isProcedure() {
	int size = tokens[_tokenIndex].size();
	vector<string> vLine = split(trim(remove(tokens[_tokenIndex], '{')), ' ');
	if ((tokens[_tokenIndex].at(size-1)=='{')
			&& (vLine.size()==2)
			&& (vLine[0].compare("procedure")==0)) {
		return true;
	}
	return false;
}
bool isRightBracket() {
	if ((tokens[_tokenIndex].compare("}")==0)) {
		return true;
	}
	return false;
}
void Parser::Match(string str) {
	int size = tokens[_tokenIndex].size();
	vector<string> vLine = split(remove(tokens[_tokenIndex], '{'), ' ');
	bool result = false;
	if (str.compare("assign")==0) {
		result = isAssignment();
	} else if (str.compare("while")==0){
		result = isWhile();
	} else if (str.compare("if")==0) {
		result = isIf();
	} else if (str.compare("else")==0) {
		result = isElse();
	} else if (str.compare("call")==0) {
		result = isCall();
	} else if (str.compare("procedure")==0) {
		result = isProcedure();
	} else if (str.compare("}")==0) {
		result = isRightBracket();
	}
	if (!result) {
		throw "Wrong SIMPLE format!!!";
	}
}

void Parser::op_Program() {
//	cout << "inProgram" << endl;
	TNode tempNode = TNode();
	tempNode.setNodeType("Program");
	tempNode.setProcLine(-1);
	_nodeList[_size] = tempNode;
	int p_main = _size;	
	_ast.setRoot(&_nodeList[p_main]);
	_size++;

	while (_tokenIndex < _tokenAmount) {
		_pos = 0;
		op_Procedure();
		_tokenIndex++;
	}
	
//	cout << "outProgram" << endl;
}

void Parser::op_Procedure() {
//	cout << "inProcedure" << endl;
	Match("procedure");
	vector<string> vLine = split(remove(tokens[_tokenIndex], '{'),' ');
	STRING proName = vLine[1];

	/*Procedure Node*/	
	int proIndex = _procTable.insertPro(proName);
	TNode tempNode = TNode();
	tempNode.setNodeType("Procedure");
	tempNode.setProcLine(-1);
	tempNode.setIndex(proIndex);
	_nodeList[_size] = tempNode;
	int p_pro = _size;
	_size++;
	_ast.createLink(&_nodeList[p_pro], &_nodeList[_pos], "isChild");
	_contains.insertContains(_nodeList[_pos].getNodeType(), _nodeList[_pos].getIndex(), _nodeList[_pos].getProcLine(), 
		_nodeList[p_pro].getNodeType(), _nodeList[p_pro].getIndex(), _nodeList[p_pro].getProcLine());
	_procedure = proIndex;
	/*StmtLst Node*/
	tempNode = TNode();
	tempNode.setNodeType("Statement");
	tempNode.setProcLine(-1);
	int ii=_stmtLstTable.insertStmtLstTable("Procedure");
	tempNode.setIndex(ii);
	_nodeList[_size] = tempNode;
	TNode* stmtLstNode = &_nodeList[_size];
	_size++;
	_ast.createLink(stmtLstNode, &_nodeList[p_pro], "isChild");	
	_contains.insertContains(_nodeList[p_pro].getNodeType(), _nodeList[p_pro].getIndex(), _nodeList[p_pro].getProcLine(),
		"StmtLst", (*stmtLstNode).getIndex(), (*stmtLstNode).getProcLine());
	_pos = _size-1;

	_tokenIndex++;
	_procTable.setProStartLine(proIndex, _progline+1);
	int start = _progline+1;
	op_StmtLst();
	_procTable.setProEndLine(proIndex, _progline);
	_stmtLstTable.setStartLine(ii, start);
	_stmtLstTable.setEndLine(ii, _progline);
/*	int ii=_stmtLstTable.insertStmtLstTable("Procedure", start, _progline);
	(*stmtLstNode).setIndex(ii);		*/
//	cout << "outProcedure" << endl;
}

void Parser::op_StmtLst() {
//	cout << "inStmtLst" << endl;
	while (!isRightBracket() && (_tokenIndex<_tokenAmount)) {
		op_Stmt();
		_tokenIndex++;
	}
//	cout << _tokenIndex << " : " << _tokenAmount << endl;
	if (_tokenIndex>=_tokenAmount) {
		throw "Wrong SIMPLE format!!!";
	}

//	cout << "outStmtLst" << endl;
}

void Parser::op_Stmt() {
//	cout << "inStmt" << endl;
	if (isAssignment()) {
		op_Assignment();
	} else if (isWhile()) {
		op_While();
	} else if (isIf()) {
		op_If();
	} else if (isCall()) {
		op_Call();
	} else {
		throw "Wrong SIMPLE format!!!";
	}
	
//	cout << "outStmt" << endl;
}

void Parser::op_While() {
//	cout << "inWhile" << endl;
//	cout << _progline << endl;
	_progline++;
	vector<string> vLine = split(remove(tokens[_tokenIndex], '{'),' ');
	/*While Node*/
	TNode tempNode = TNode();
	tempNode.setNodeType("While");
	tempNode.setProcLine(_progline);
	_nodeList[_size] = tempNode;
	int p_while = _size;
	_size++;
	TNode* currentNode = &_nodeList[_pos];
	if ((*currentNode).getNodeType().compare("Statement")==0) { 
		_ast.createLink(&_nodeList[p_while],currentNode,"isChild");
		_contains.insertContains("StmtLst", (*currentNode).getIndex(), (*currentNode).getProcLine(),
		_nodeList[p_while].getNodeType(), _nodeList[p_while].getIndex(), _nodeList[p_while].getProcLine());
	} else if ((*currentNode).getNodeType().compare("StmtLst")==0) {
		_parent.setParentPair((*(*currentNode).getParent()).getProcLine(), _progline);	
		_ast.createLink(&_nodeList[p_while],currentNode,"isChild");
		_contains.insertContains((*currentNode).getNodeType(), (*currentNode).getIndex(), (*currentNode).getProcLine(),
		_nodeList[p_while].getNodeType(), _nodeList[p_while].getIndex(), _nodeList[p_while].getProcLine());
	} else {
		_follows.setFollows((*currentNode).getProcLine(), _progline);
		_ast.createLink(&_nodeList[p_while], currentNode, "isRightSibling");
		TNode* parent = (*currentNode).getParent();
		if ((*parent).getNodeType().compare("StmtLst")==0) {
			_parent.setParentPair((*(*parent).getParent()).getProcLine(), _progline);
		}		
		_ast.createLink(&_nodeList[p_while],parent,"isChild");
		string pNT = (*parent).getNodeType();
		if (pNT=="Statement") pNT="StmtLst";
		_contains.insertContains(pNT, (*parent).getIndex(), (*parent).getProcLine(),
		_nodeList[p_while].getNodeType(), _nodeList[p_while].getIndex(), _nodeList[p_while].getProcLine());
	}

	/*Variable Node*/
	STRING varName = vLine[1];
	int varTableIndex = _varTable.inSertVar(varName);
	_uses.setUses(_progline, _procedure, varTableIndex);
	int tempLine = _progline;
	while(_parent.getMyParent(tempLine)!=-1)
	{
		tempLine = _parent.getMyParent(tempLine);
		_uses.setUses(tempLine, _procedure, varTableIndex);
	}

	_patternTable.insertPattern(2, _progline, varName, vector<Pattern_node>());
	tempNode = TNode();
	tempNode.setNodeType("Variable");
	tempNode.setProcLine(-1);
	tempNode.setIndex(varTableIndex);
	_nodeList[_size] = tempNode;	
	TNode* varNode = &_nodeList[_size];
	_size++;
	_ast.createLink(varNode, &_nodeList[p_while], "isChild");
	_contains.insertContains(_nodeList[p_while].getNodeType(), _nodeList[p_while].getIndex(), _nodeList[p_while].getProcLine(),
		(*varNode).getNodeType(), (*varNode).getIndex(), (*varNode).getProcLine());

	/*StmtLst Node*/
	tempNode = TNode();
	tempNode.setNodeType("StmtLst");
	tempNode.setProcLine(-1);
	int ii=_stmtLstTable.insertStmtLstTable("While");
	tempNode.setIndex(ii);
	_nodeList[_size] = tempNode;
	TNode* stmtLstNode = &_nodeList[_size];
	_size++;
	_ast.createLink(stmtLstNode, &_nodeList[p_while], "isChild");	
	_contains.insertContains(_nodeList[p_while].getNodeType(), _nodeList[p_while].getIndex(), _nodeList[p_while].getProcLine(),
		(*stmtLstNode).getNodeType(), (*stmtLstNode).getIndex(), (*stmtLstNode).getProcLine());
	_pos = _size-1;

	_tokenIndex++;
	int start = _progline+1;
	op_StmtLst();
	_stmtLstTable.setStartLine(ii,start);
	_stmtLstTable.setEndLine(ii, _progline);
/*	int ii=_stmtLstTable.insertStmtLstTable("While", start, _progline);
	(*stmtLstNode).setIndex(ii);*/
	_pos = p_while;
	
//	cout << "outWhile" << endl;
}

void Parser::op_If() {
//	cout << "inIf" << endl;
//	cout << _progline << endl;
	_progline++;
	vector<string> vLine = split(remove(tokens[_tokenIndex], '{'),' ');
	/*If Node*/
	TNode tempNode = TNode();
	tempNode.setNodeType("If");
	tempNode.setProcLine(_progline);
	_nodeList[_size] = tempNode;
	int p_if = _size;
	_size++;
	TNode* currentNode = &_nodeList[_pos];
	if ((*currentNode).getNodeType().compare("Statement")==0) { 
		_ast.createLink(&_nodeList[p_if],currentNode,"isChild");
		_contains.insertContains("StmtLst", (*currentNode).getIndex(), (*currentNode).getProcLine(),
		_nodeList[p_if].getNodeType(), _nodeList[p_if].getIndex(), _nodeList[p_if].getProcLine());
	} else if ((*currentNode).getNodeType().compare("StmtLst")==0) {
		_parent.setParentPair((*(*currentNode).getParent()).getProcLine(), _progline);		
		_ast.createLink(&_nodeList[p_if],currentNode,"isChild");
		_contains.insertContains((*currentNode).getNodeType(), (*currentNode).getIndex(), (*currentNode).getProcLine(),
		_nodeList[p_if].getNodeType(), _nodeList[p_if].getIndex(), _nodeList[p_if].getProcLine());
	} else {
		_follows.setFollows((*currentNode).getProcLine(), _progline);
		_ast.createLink(&_nodeList[p_if], currentNode, "isRightSibling");
		TNode* parent = (*currentNode).getParent();
		if ((*parent).getNodeType().compare("StmtLst")==0) {
			_parent.setParentPair((*(*parent).getParent()).getProcLine(), _progline);
		}		
		_ast.createLink(&_nodeList[p_if],parent,"isChild");
		string pNT = (*parent).getNodeType();
		if (pNT=="Statement") pNT="StmtLst";
		_contains.insertContains(pNT, (*parent).getIndex(), (*parent).getProcLine(),
		_nodeList[p_if].getNodeType(), _nodeList[p_if].getIndex(), _nodeList[p_if].getProcLine());
	}

	/*Variable Node*/
	STRING varName = remove(vLine[1],'{');
	_patternTable.insertPattern(1, _progline, varName, vector<Pattern_node>());
	int varTableIndex = _varTable.inSertVar(varName);
	_uses.setUses(_progline, _procedure, varTableIndex);
	int tempLine = _progline;
	while(_parent.getMyParent(tempLine)!=-1)
	{
		tempLine = _parent.getMyParent(tempLine);
		_uses.setUses(tempLine, _procedure, varTableIndex);
	}
	tempNode = TNode();
	tempNode.setNodeType("Variable");
	tempNode.setProcLine(-1);
	tempNode.setIndex(varTableIndex);
	_nodeList[_size] = tempNode;	
	TNode* varNode = &_nodeList[_size];
	_size++;
	_ast.createLink(varNode, &_nodeList[p_if], "isChild");
	_contains.insertContains(_nodeList[p_if].getNodeType(), _nodeList[p_if].getIndex(), _nodeList[p_if].getProcLine(),
		(*varNode).getNodeType(), (*varNode).getIndex(), (*varNode).getProcLine());
	/*StmtLst Node*/
	tempNode = TNode();
	tempNode.setNodeType("StmtLst");
	tempNode.setProcLine(-1);
	int ii = _stmtLstTable.insertStmtLstTable("If");
	tempNode.setIndex(ii);
	_nodeList[_size] = tempNode;
	TNode* stmtLstNode = &_nodeList[_size];
	_size++;
	_ast.createLink(stmtLstNode, &_nodeList[p_if], "isChild");
	_contains.insertContains(_nodeList[p_if].getNodeType(), _nodeList[p_if].getIndex(), _nodeList[p_if].getProcLine(),
		(*stmtLstNode).getNodeType(), (*stmtLstNode).getIndex(), (*stmtLstNode).getProcLine());
	_pos = _size-1;

	_tokenIndex++;

	int start = _progline+1;
	op_StmtLst();
	_stmtLstTable.setStartLine(ii, start);
	_stmtLstTable.setEndLine(ii, _progline);
/*	int ii = _stmtLstTable.insertStmtLstTable("If", start, _progline);
	(*stmtLstNode).setIndex(ii);*/
	
	/*else Node*/
	_tokenIndex++;
	Match("else");

	tempNode = TNode();
	tempNode.setNodeType("StmtLst");
	tempNode.setProcLine(-1);	
	ii = _stmtLstTable.insertStmtLstTable("If");
	tempNode.setIndex(ii);
	_nodeList[_size] = tempNode;
	TNode* stmtLstNode2 = &_nodeList[_size];
	_size++;
	_ast.createLink(stmtLstNode2, &_nodeList[p_if], "isChild");	
	_contains.insertContains(_nodeList[p_if].getNodeType(), _nodeList[p_if].getIndex(), _nodeList[p_if].getProcLine(),
		(*stmtLstNode2).getNodeType(), (*stmtLstNode2).getIndex(), (*stmtLstNode2).getProcLine());
	_pos = _size-1;
	_tokenIndex++;
	
	start = _progline+1;
	op_StmtLst();	
	_stmtLstTable.setStartLine(ii, start);
	_stmtLstTable.setEndLine(ii, _progline);
/*	ii = _stmtLstTable.insertStmtLstTable("If", start, _progline);
	(*stmtLstNode2).setIndex(ii);*/

	_pos = p_if;
//	cout << "outIf" << endl;
}

int Level(string m){
	if((m.compare("+") ==0)||(m.compare("-")==0)){
		return 1;
	}
	if((m.compare("*") ==0)||(m.compare("/")==0)){
		return 2;
	}
	if((m.compare("(") ==0)||(m.compare(")")==0)){
		return 0;
	}
	else return -1;
}


vector<string> sp(string vecExp){
	vector<string> result = vector<string>();
	string tempString = "";
	bool empty = true;
	for(int i = 0; i <vecExp.size();i++){
		char temp = vecExp.at(i);
		switch(temp){
		case '(':
		case ')':
		case '+':
		case '-':
		case '/':
		case '*':
			if (tempString.compare("")!=0) result.push_back(tempString);
			tempString = "";
			tempString.append(1,temp);
			result.push_back(tempString);
			tempString = "";
			break;
		default:
			tempString.append(1,temp);
			break;
		}
	}
	if (tempString.compare("")!=0) result.push_back(tempString);
	return result;
}

string getNodeType(string op) {
	string result = "";
	if (op.compare("+")==0) {
		result = "Plus";
	} else if (op.compare("-")==0) {
		result = "Minus";
	} else if (op.compare("*")==0) {
		result = "Times";
	}
	return result;
}

int Parser::getOpIndex(string op) {
	int result=-1;
	if (op.compare("+")==0) {
		result = _plusTable.insertPlus(_progline);
	} else if (op.compare("-")==0) {
		result = _minusTable.insertMinus(_progline);
	} else if (op.compare("*")==0) {
		result = _timesTable.insertTimes(_progline);
	}
	return result;
}

void Parser::reLevel(TNode *node){	
	node->setLevel((*node->getParent()).getLevel()+1);
	
	Pattern_node temp = Pattern_node();
	int index;
	string data;
	if (node->getNodeType().compare("Constant")==0) {		
		index = node->getIndex();
		int temp = _constTable.getConstant(index);
		stringstream ss;
		ss<<temp;
		data = ss.str();
	} else if (node->getNodeType().compare("Variable")==0) {
		index = node->getIndex();
		data = _varTable.getVarName(index);
	} else {
		data = node->getNodeType();
	}
	temp.setData(data);
	patternTree.push_back(temp);
	int pos = patternTree.size()-1;

	int numOfChild = node->getNumOfMoreChild();
	int _size;
	if (numOfChild > 0) {
		TNode* left = node->getMoreChildren()[0];
		_size = patternTree.size();
		patternTree.at(pos).setLeft(_size);
		reLevel(left);

		TNode* right = node->getMoreChildren()[1];
		_size = patternTree.size();
		patternTree.at(pos).setRight(_size);	
		reLevel(right);
	}
/*	
	for(int i = 0; i < node->getNumOfMoreChild();i++){
		reLevel((node->getMoreChildren())[i]);
	}*/
}


void Parser::op_Assignment(){
//	cout << "inAssignment" << endl;	
//	cout << _progline << endl;
	_progline++;
	string assign = tokens[_tokenIndex];
	stack<int> varStack = stack<int>();
	stack<string> opStack = stack<string>();

	vector<string> vecLine  = split(remove(trim(remove(assign, ';')),' '),'=');
	TNode tempNode = TNode();
	tempNode.setProcLine(_progline);
	tempNode.setNodeType("Assign");
    
    
	_nodeList[_size] = tempNode;
	int p_assign = _size;
	_size++;

	TNode* current = &_nodeList[_pos];
    
	if ((*current).getNodeType().compare("Statement")==0) { 
		_ast.createLink(&_nodeList[p_assign],current,"isChild");
		_contains.insertContains("StmtLst", (*current).getIndex(), (*current).getProcLine(),
		_nodeList[p_assign].getNodeType(), _nodeList[p_assign].getIndex(), _nodeList[p_assign].getProcLine());
	} else if ((*current).getNodeType().compare("StmtLst")==0) {
		_parent.setParentPair((*(*current).getParent()).getProcLine(), _nodeList[p_assign].getProcLine());
		_ast.createLink(&_nodeList[p_assign],current,"isChild");
		_contains.insertContains((*current).getNodeType(), (*current).getIndex(), (*current).getProcLine(),
		_nodeList[p_assign].getNodeType(), _nodeList[p_assign].getIndex(), _nodeList[p_assign].getProcLine());
	}
	else{
		TNode* parent = (*current).getParent();
		if ((*parent).getNodeType().compare("StmtLst")==0) {
			_parent.setParentPair((*(*parent).getParent()).getProcLine(), _nodeList[p_assign].getProcLine());
		}		
		_follows.setFollows((*current).getProcLine(), _nodeList[p_assign].getProcLine());
		_ast.createLink(&_nodeList[p_assign],current,"isRightSibling");
		_ast.createLink(&_nodeList[p_assign],parent,"isChild");
		string pNT = (*parent).getNodeType();
		if (pNT=="Statement") pNT="StmtLst";
		_contains.insertContains(pNT, (*parent).getIndex(), (*parent).getProcLine(),
		_nodeList[p_assign].getNodeType(), _nodeList[p_assign].getIndex(), _nodeList[p_assign].getProcLine());
	}
	
	tempNode = TNode();
	int index = _varTable.inSertVar(vecLine[0]);
	tempNode.setIndex(index);
	tempNode.setNodeType("Variable");
	_nodeList[_size] = tempNode;
	TNode* varNode = &_nodeList[_size];
	_size++;
	_ast.createLink(varNode,&_nodeList[p_assign],"isChild");  
	_contains.insertContains(_nodeList[p_assign].getNodeType(), _nodeList[p_assign].getIndex(), _nodeList[p_assign].getProcLine(),
		(*varNode).getNodeType(), (*varNode).getIndex(), (*varNode).getProcLine());
	vector<string> vecExp  = sp(vecLine[1]);
/*	for (int i=0; i<vecExp.size(); i++) {
		cout << vecExp[i] << endl;
	}*/
	opStack.push("(");
	for(int i = 0; i < vecExp.size()+1;i++){
		string temp;
		if(i == vecExp.size())
			temp = ")";
		else temp = vecExp.at(i);

		if(temp.compare("(")==0){
			opStack.push(temp);
		} else if(temp.compare(")")==0){
			vector<string> Ops = vector<string>();
			vector<int> Vars = vector<int>();
			for(;opStack.top()!="(";opStack.pop()) {
				string op = opStack.top();
				Ops.push_back(op);
				int varIndex = varStack.top();
				Vars.push_back(varIndex);
				varStack.pop();
			}
			opStack.pop();
			if (Ops.size()==0) continue;
			string operation = Ops.back();
			int var1, var2;
			var1 = varStack.top();
			var2 = Vars.back();
			int lastLevel = Level(operation);
			varStack.pop();
			for(int i=Ops.size()-1; i>0; i--) {
				string op = Ops[i-1];
				int var = Vars[i-1];
				int level = Level(op);
				if (lastLevel<level) {
					TNode node = TNode();
					string nodeType = op;
					int index = getOpIndex(nodeType);
					node.setNodeType(nodeType);
					node.setIndex(index);
					_nodeList[_size] = node;
					_ast.createLink(&_nodeList[var2], &_nodeList[_size], "isChild");
					_contains.insertContains(_nodeList[_size].getNodeType(), _nodeList[_size].getIndex(), _nodeList[_size].getProcLine(),
						_nodeList[var2].getNodeType(), _nodeList[var2].getIndex(), _nodeList[var2].getProcLine());
					_ast.createLink(&_nodeList[var], &_nodeList[_size], "isChild");
					_contains.insertContains(_nodeList[_size].getNodeType(), _nodeList[_size].getIndex(), _nodeList[_size].getProcLine(),
						_nodeList[var].getNodeType(), _nodeList[var].getIndex(), _nodeList[var].getProcLine());
					_ast.createLink(&_nodeList[var1], &_nodeList[var], "isRightSibling");
				
					var2 = _size;
					_size++;
				} else {
					lastLevel = level;
					TNode node = TNode();
					string nodeType = operation;
					int index = getOpIndex(nodeType);
					node.setNodeType(nodeType);
					node.setIndex(index);
					_nodeList[_size] = node;
					_ast.createLink(&_nodeList[var1], &_nodeList[_size], "isChild");
					_contains.insertContains(_nodeList[_size].getNodeType(), _nodeList[_size].getIndex(), _nodeList[_size].getProcLine(),
						_nodeList[var1].getNodeType(), _nodeList[var1].getIndex(), _nodeList[var1].getProcLine());
					_ast.createLink(&_nodeList[var2], &_nodeList[_size], "isChild");
					_contains.insertContains(_nodeList[_size].getNodeType(), _nodeList[_size].getIndex(), _nodeList[_size].getProcLine(),
						_nodeList[var2].getNodeType(), _nodeList[var2].getIndex(), _nodeList[var2].getProcLine());
					_ast.createLink(&_nodeList[var1], &_nodeList[var2], "isRightSibling");
					var1 = _size;
					operation = op;
					var2 = var;
					_size++;
				}
			}
			TNode node = TNode();
			string nodeType = operation;
			int index = getOpIndex(nodeType);
			node.setNodeType(nodeType);
			node.setIndex(index);
			_nodeList[_size] = node;
			_ast.createLink(&_nodeList[var1], &_nodeList[_size], "isChild");
			_contains.insertContains(_nodeList[_size].getNodeType(), _nodeList[_size].getIndex(), _nodeList[_size].getProcLine(),
						_nodeList[var1].getNodeType(), _nodeList[var1].getIndex(), _nodeList[var1].getProcLine());
			_ast.createLink(&_nodeList[var2], &_nodeList[_size], "isChild");
			_contains.insertContains(_nodeList[_size].getNodeType(), _nodeList[_size].getIndex(), _nodeList[_size].getProcLine(),
						_nodeList[var2].getNodeType(), _nodeList[var2].getIndex(), _nodeList[var2].getProcLine());
			_ast.createLink(&_nodeList[var1], &_nodeList[var2], "isRightSibling");
			varStack.push(_size);
			_size++;
		}
		else if(Level(temp)<0){
			TNode node = TNode();
			if (!isConstant(temp)){
				int tempIndex = _varTable.inSertVar(temp);
				node.setIndex(tempIndex);
				node.setNodeType("Variable");
			}
			else{
				node.setNodeType("Constant");
				int i = atoi(temp.c_str());
				int tempIndex = _constTable.insertCon(i);
				node.setIndex(tempIndex);
			}
			_nodeList[_size] = node;			
			varStack.push(_size);
			_size++;
		}
		else{
			opStack.push(temp);
		}
        
	}
	int root = varStack.top();
    _ast.createLink(&_nodeList[root], &_nodeList[p_assign],"isChild");
	_contains.insertContains(_nodeList[p_assign].getNodeType(), _nodeList[p_assign].getIndex(), _nodeList[p_assign].getProcLine(),
						_nodeList[root].getNodeType(), _nodeList[root].getIndex(), _nodeList[root].getProcLine());
    _ast.createLink(&_nodeList[root], varNode,"isRightSibling");
	/* for Pattern Table  */
	patternTree = vector<Pattern_node>();
//	cout<<"root:" <<_nodeList[root].getNodeType()<<endl;
	reLevel(&_nodeList[root]);
/*	
	for (int i=0; i<patternTree.size(); i++) {
		if (Level(patternTree[i].getData())>0) {
			patternTree[i].setLeft(i+1);
			patternTree[i].setRight(i+2);
		}
	}*/
/*	for (int i=0; i<patternTree.size(); i++) {
		cout<<patternTree[i].getData()<<" ";
	}
	cout<<endl;*/
	//Uses
	for(int i = 0; i < vecExp.size();i++)
	{
		if((Level(vecExp[i])<0)&&(!isConstant(vecExp[i]))){
			int tempIndex = _varTable.inSertVar(vecExp[i]);
			_uses.setUses(_progline, _procedure, tempIndex);
			int tempLine = _progline;
			while(_parent.getMyParent(tempLine) != -1)
			{
				tempLine = _parent.getMyParent(tempLine);
				_uses.setUses(tempLine, _procedure, tempIndex);
			}
		}
	}

	//Modifies
	int tempIndex = _varTable.inSertVar(vecLine[0]);
	_modifies.setModifies(_progline, _procedure, tempIndex);
	int tempLine = _progline;
	while(_parent.getMyParent(tempLine)!= -1)
	{
		tempLine = _parent.getMyParent(tempLine);
		_modifies.setModifies(tempLine, _procedure, tempIndex);
	}
	//set _pos to the current index of the assign node;
	_pos = p_assign;
	//Pattern
	_patternTable.insertPattern(0, _progline, vecLine[0],patternTree);
	
//	cout << "outAssignment" << endl;
} 


void Parser::op_Call() {
//	cout << "inCall" << endl;		
//	cout << _progline << endl;
	_progline++;
	vector<string> vLine = split(tokens[_tokenIndex], ' ');
	STRING proName = vLine[1];

	/*Call Node*/	
	int proIndex = _procTable.insertPro(proName);
	TNode tempNode = TNode();
	tempNode.setNodeType("Call");
	tempNode.setProcLine(_progline);
	tempNode.setIndex(proIndex);
	_nodeList[_size] = tempNode;
	int p_call = _size;
	_size++;
	_calls.setCall(_progline, _procedure, proIndex);

	TNode* currentNode = &_nodeList[_pos];
	if ((*currentNode).getNodeType().compare("Statement")==0) { 
		_ast.createLink(&_nodeList[p_call],currentNode,"isChild");
		_contains.insertContains("StmtLst", (*currentNode).getIndex(), (*currentNode).getProcLine(),
		_nodeList[p_call].getNodeType(), _nodeList[p_call].getIndex(), _nodeList[p_call].getProcLine());
	} else if ((*currentNode).getNodeType().compare("StmtLst")==0) {
		_parent.setParentPair((*(*currentNode).getParent()).getProcLine(), _progline);		
		_ast.createLink(&_nodeList[p_call],currentNode,"isChild");
		_contains.insertContains((*currentNode).getNodeType(), (*currentNode).getIndex(), (*currentNode).getProcLine(),
		_nodeList[p_call].getNodeType(), _nodeList[p_call].getIndex(), _nodeList[p_call].getProcLine());
	} else {
		_follows.setFollows((*currentNode).getProcLine(), _progline);
		_ast.createLink(&_nodeList[p_call], currentNode, "isRightSibling");
		TNode* parent = (*currentNode).getParent();
		if ((*parent).getNodeType().compare("StmtLst")==0) {
			_parent.setParentPair((*(*parent).getParent()).getProcLine(), _progline);
		}		
		_ast.createLink(&_nodeList[p_call],parent,"isChild");
		string pNT = (*parent).getNodeType();
		if (pNT=="Statement") pNT="StmtLst";
		_contains.insertContains(pNT, (*parent).getIndex(), (*parent).getProcLine(),
		_nodeList[p_call].getNodeType(), _nodeList[p_call].getIndex(), _nodeList[p_call].getProcLine());
	}


	// LoopTable : Find if this Call is in any while-loop or IF-statement
	int tempLine = _progline;
	while(_parent.getMyParent(tempLine)!= -1)
	{
		tempLine = _parent.getMyParent(tempLine);
		_loopTable.setLoop(tempLine, _procedure, proIndex);
	}


	_pos = p_call;
	
//	cout << "outCall" << endl;
}


Parser::Parser() {
	_sLine = "";
	_level = 0;
	_progline = 0; 
	_pos = 0;
	_size = 0;
	_tokenIndex = 0;
	_tokenAmount = 0;
	_ast = AST();
	_varTable = VarTable();
	_procTable = ProcTable();
	_constTable = ConstTable();
	_patternTable = PatternTable();
	_parent = Parent();
	_follows = Follows();
	_modifies = Modifies();
	_uses = Uses();
	_calls = Calls();
	_loopTable = LoopTable();
	_stmtLstTable = StmtLstTable();
	_plusTable = PlusTable();
	_minusTable = MinusTable();
	_timesTable = TimesTable();
	_contains = Contains();
}

Parser::Parser(STRING fileName) {	
	_sLine = "";
	_level = 0;
	_progline = 0; 
	_pos = 0;
	_size = 0;
	_tokenIndex = 0;
	_tokenAmount = 0;
	char c;
	_infile.open(fileName);
	while (_infile.get(c)) {
		_sLine = _sLine + c;
		if ((c=='}') || (c=='{') || (c==';')) {
			tokens.push_back(trim(remove(_sLine, ';')));		
			_tokenAmount++;
			_sLine = "";
		}
	}
	_infile.close();
/*	cout << _tokenAmount <<endl;
	for (int i=0; i<_tokenAmount; i++) {
		cout << tokens[i] << endl;
	}
*/
	op_Program();

/*
	for (int i=0; i<_size; i++) {
		cout << i << ".  " << _nodeList[i].getNodeType() << endl;
	}*/
	_ast.setTotalLineNum(_progline);
//	_contains.computeContainsStar();
}